package org.jeecg.modules.openApi.controller;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.text.StringSubstitutor;
import org.jeecg.alibaba.api.IdCardOCR;
import org.jeecg.alibaba.vo.IdCardVo;
import org.jeecg.cmbCloudDirectLink.utils.GENKey;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.config.mqtoken.UserTokenContext;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.*;
import org.jeecg.eSign.constant.EsignConfig;
import org.jeecg.eSign.utils.ESignUtils;
import org.jeecg.modules.manage.entity.*;
import org.jeecg.modules.manage.service.*;
import org.jeecg.wx.constant.WXConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.security.spec.AlgorithmParameterSpec;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * @Description: 微信小程序接口
 * @Author: yfkj
 * @Date:   2023-01-03
 * @Version: V1.0
 */
@Api(tags="微信小程序接口")
@RestController
@RequestMapping("/appletApi/signing")
@Slf4j
public class AppletApiController {

	@Autowired
	private IMCaishuiServiceCompanyService imCaishuiServiceCompanyService;
	@Autowired
	private IMCaishuiBusinessService imCaishuiBusinessService;
	@Autowired
	private IMCaishuiMemberService imCaishuiMemberService;
	@Autowired
	private IMCaishuiServiceTaskService imCaishuiServiceTaskService;
	@Autowired
	private IMCaishuiSigningServiceTypeService imCaishuiSigningServiceTypeService;
	@Autowired
	private IMCaishuiPreItemsService imCaishuiPreItemsService;
	@Resource
	private ISysBaseAPI iSysBaseAPI;

	@Value("${jeecg.path.upload}")
	private String upLoadPath;//文件上传根目录
	@Value("${jeecg.file-view-domain}")
	private String fileViewDomain;//在线预览文件服务器地址

	/**
	 * 获取openid和sessionkey
	 * @param code
	 * @return
	 */
	@ApiOperation(value = "获取openid和sessionkey", notes = "获取openid和sessionkey")
	@GetMapping(value = "/getSessionkey")
	public Result<?> getSessionkey(@RequestParam(name="code",required=true) String code) {
		Map<String, String> requestUrlParam = new HashMap<>();
		//小程序appId
		requestUrlParam.put("appid", WXConstant.appId);
		//小程序secret
		requestUrlParam.put("secret", WXConstant.appSecret);
		//小程序端返回的code
		requestUrlParam.put("js_code", code);
		//默认参数
		requestUrlParam.put("grant_type", "authorization_code");
		//发送post请求读取调用微信接口获取openid用户唯一标识
		JSONObject jsonObject = JSON.parseObject(HttpClientUtils.doPost(WXConstant.jscode2session_url, requestUrlParam));
		return Result.ok(jsonObject);
	}

	/**
	 * 通过用户授权加密信息解密获取手机号
	 * @param encrypdata
	 * @param ivdata
	 * @param sessionkey
	 * @return
	 */
	@ApiOperation(value = "通过用户授权加密信息解密获取手机号", notes = "通过用户授权加密信息解密获取手机号")
	@GetMapping(value = "/getPhoneByKey")
	public Result<Object> getPhoneByKey(@RequestParam(name="encrypdata",required=true) String encrypdata,
										@RequestParam(name="ivdata",required=true) String ivdata,
										@RequestParam(name="sessionkey",required=true) String sessionkey) {
		//字符串转base64
		byte[] byEncrypdata = Base64.decodeBase64(encrypdata);
		byte[] byIvdata = Base64.decodeBase64(ivdata);
		byte[] bySessionkey = Base64.decodeBase64(sessionkey);

		AlgorithmParameterSpec ivSpec = new IvParameterSpec(byIvdata);
		Cipher cipher;
		try {
			SecretKeySpec keySpec = new SecretKeySpec(bySessionkey, "AES");
			cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
			cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
			String phone = new String(cipher.doFinal(byEncrypdata),"UTF-8");
			return Result.ok("解密成功！",phone);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return Result.error(e.getMessage());
		}
	}

	/**
	 * 查询用户协议和隐私政策
	 * @return
	 */
	@ApiOperation(value = "查询用户协议和隐私政策", notes = "查询用户协议和隐私政策")
	@GetMapping(value = "/queryPrivacyAgreement")
	public Result<?> queryPrivacyAgreement() {
		//1.设置线程会话Token
		UserTokenContext.setToken(getTemporaryToken());
		String content = iSysBaseAPI.queryArticleByCode("A01A02");
		if (oConvertUtils.isEmpty(content)) return Result.error("文章不存在！");
		//2.使用完删除Token
		UserTokenContext.remove();
		return Result.ok("查询成功！",content);
	}

	/**
	 * 查询签约任务信息
	 *
	 * @param id
	 * @return
	 */
	@ApiOperation(value = "查询签约任务信息", notes = "查询签约任务信息")
	@GetMapping(value = "/queryServiceTaskById")
	public Result<?> queryServiceTaskById(@RequestParam(name="id",required=true) String id,
										  @RequestParam(name="phone",required=true) String phone) {
		Map<String, String> result = new HashMap<>();
		//签约任务
		CaishuiServiceTask serviceTask = imCaishuiServiceTaskService.getById(id);
		if(oConvertUtils.isEmpty(serviceTask)){
			return Result.error("签约任务不存在！");
		}else if(serviceTask.getStatus() != 1){
			return Result.error("签约任务已关闭！");
		}
		result.put("signingStatus","0");//签约状态：0-未签约，1-已签约
		//根据手机号查询该服务公司、签约商户的人才
		CaishuiMember member = imCaishuiMemberService.getOne(new LambdaQueryWrapper<CaishuiMember>()
				.eq(CaishuiMember::getCompanyId,serviceTask.getCompanyId()).eq(CaishuiMember::getBusinessId,serviceTask.getBusinessId())
				.eq(CaishuiMember::getPhone,phone));
		if(oConvertUtils.isNotEmpty(member) && member.getStatus() == 2){
			result.put("signingStatus","1");
		}
		result.put("companyId",serviceTask.getCompanyId());
		result.put("businessId",serviceTask.getBusinessId());
		result.put("releaseDate", DateUtils.sdf.format(serviceTask.getCreateTime()));
		//公司信息
		CaishuiServiceCompany company = imCaishuiServiceCompanyService.getById(serviceTask.getCompanyId());
		if(oConvertUtils.isEmpty(company)){
			return Result.error("服务公司不存在！");
		}
		result.put("companyName",company.getName());
		result.put("companyCode",company.getBusinessLicenseNo());
		//商户信息
		CaishuiBusiness business = imCaishuiBusinessService.getById(serviceTask.getBusinessId());
		if(oConvertUtils.isEmpty(business)){
			return Result.error("签约商户不存在！");
		}
		result.put("businessName",business.getName());
		result.put("tenantId",business.getTenantId()+"");
		//签约服务类型
		String signingService = imCaishuiSigningServiceTypeService.queryServiceTypeByIds(serviceTask.getSigningService());
		result.put("signingServiceId",serviceTask.getSigningService());
		result.put("signingService",signingService);
		//签约文件内容
		String content = imCaishuiMemberService.querySigningContent();
		Map<String,String> replaceMap = new HashMap<String,String>();
		replaceMap.put("companyName",company.getName());
		replaceMap.put("companyCode",company.getBusinessLicenseNo());
		replaceMap.put("businessName",business.getName());
		replaceMap.put("serviceType",signingService);
		replaceMap.put("name","");
		replaceMap.put("idCard","");
		replaceMap.put("signDate",DateUtils.sdf4.format(new Date()));
		result.put("signContent",new StringSubstitutor(replaceMap).replace(content));
		return Result.OK(result);
	}



	/**
	 *  添加签约人才
	 *
	 * @param caishuiMember
	 * @return
	 */
	@ApiOperation(value = "添加签约人才", notes = "添加签约人才")
	@PostMapping(value = "/addMember")
	public Result<?> addMember(@RequestBody CaishuiMember caishuiMember) throws ParseException {
		if(oConvertUtils.isEmpty(caishuiMember.getCompanyId()) || oConvertUtils.isEmpty(caishuiMember.getBusinessId())
				|| oConvertUtils.isEmpty(caishuiMember.getTenantId()) || oConvertUtils.isEmpty(caishuiMember.getSigningServiceId())
				|| oConvertUtils.isEmpty(caishuiMember.getName()) || oConvertUtils.isEmpty(caishuiMember.getIdCard())
				|| oConvertUtils.isEmpty(caishuiMember.getPhone()) || oConvertUtils.isEmpty(caishuiMember.getBankCardAccount())
				|| oConvertUtils.isEmpty(caishuiMember.getIdCardZm()) || oConvertUtils.isEmpty(caishuiMember.getIdCardFm())){
			return Result.error("参数错误！");
		}
		if(caishuiMember.getPhone().length() != 11){
			return Result.error("手机号码错误！");
		}
		if(!IdcardValidator.isValidatedAllIdcard(caishuiMember.getIdCard())){
			return Result.error("身份证号码错误！");
		}

		//根据身份证获取年龄
		int age = IdcardValidator.getAgeForIdcard(caishuiMember.getIdCard());
		if(age < 16 || age > 65){
			return Result.error("身份证年龄不符合报税要求(16-65岁)！");
		}

		//判断该人才是否已存在（只需要判断身份证号码）
		CaishuiMember member = imCaishuiMemberService.getOne(QueryGenerator.initQueryWrapper(new CaishuiMember(),null).lambda()
				.eq(CaishuiMember::getBusinessId, caishuiMember.getBusinessId()).eq(CaishuiMember::getCompanyId,caishuiMember.getCompanyId())
				.eq(CaishuiMember::getIdCard,caishuiMember.getIdCard()),false);
		if(oConvertUtils.isNotEmpty(member)){
			return Result.OK("添加成功！",member.getId());
		}

		//获取身份证正面照数据——阿里云市场
		IdCardVo idCardVoZ = IdCardOCR.queryIdCardZ(fileViewDomain + "/" + caishuiMember.getIdCardZm());
		if (oConvertUtils.isEmpty(idCardVoZ)) return Result.error("请上传正确的身份证正面照！");
		if (!caishuiMember.getName().trim().equals(idCardVoZ.getName()) ||
			!caishuiMember.getIdCard().trim().equals(idCardVoZ.getNumber())) {
			return Result.error("请输入正确的姓名和身份证号码！");
		}else {
			caishuiMember.setName(idCardVoZ.getName());
			caishuiMember.setSex(idCardVoZ.getSex());
			caishuiMember.setNation(idCardVoZ.getNation());
			caishuiMember.setBirthday(idCardVoZ.getBirthday());
			caishuiMember.setIdCard(idCardVoZ.getNumber());
			caishuiMember.setIdCardAddress(idCardVoZ.getAddress());
		};

		//获取身份证反面照数据——阿里云市场
		IdCardVo idCardVoF = IdCardOCR.queryIdCardF(fileViewDomain + "/" + caishuiMember.getIdCardFm());
		if (oConvertUtils.isEmpty(idCardVoF)) return Result.error("请上传正确的身份证反面照！");
		caishuiMember.setIdCardOffice(idCardVoF.getAuthority());
		caishuiMember.setIdCardValid(idCardVoF.getTimelimit());

		//添加预充值记录
		CaishuiPreItems preItems = new CaishuiPreItems();
		preItems.setCreateBy(caishuiMember.getPhone());
		preItems.setCreateTime(new Date());
		preItems.setCompanyId(caishuiMember.getCompanyId());
		preItems.setBusinessId(caishuiMember.getBusinessId());
		preItems.setTenantId(caishuiMember.getTenantId());
		preItems.setPreType(4);
		preItems.setPreRealname(caishuiMember.getName());
		preItems.setPreIdCard(caishuiMember.getIdCard());
		preItems.setPreNum(2);
		//1.设置线程会话Token
		UserTokenContext.setToken(getTemporaryToken());
		double price = oConvertUtils.getDouble(iSysBaseAPI.queryValueByCode("A01A03"),0);
		//2.使用完删除Token
		UserTokenContext.remove();
		if (price <= 0) return Result.error("预充值未配置，请联系管理员！");
		preItems.setPrePrice(price);
		preItems.setPreAmount(price*2);
		preItems.setPreStatus(1);
		preItems.setPreRemarks("电子签约");
		imCaishuiPreItemsService.save(preItems);

		//保存签约人才
		caishuiMember.setCreateBy(caishuiMember.getPhone());
		caishuiMember.setCreateTime(new Date());
		caishuiMember.setNickName("微信用户");
		caishuiMember.setCode(GENKey.genRandomString(new Random(), "0123456789", 8));
		caishuiMember.setIdCardType(1);
		caishuiMember.setBankCardType("OTHERBANK");
		caishuiMember.setSigningType(1);
		caishuiMember.setSigningStatus(0);//待签约
		imCaishuiMemberService.save(caishuiMember);
		return Result.OK("添加成功！",caishuiMember.getId());
	}

	/**
	 * 编辑签约人才（签约）
	 * @param caishuiMember
	 * @return
	 */
	@ApiOperation(value = "编辑签约人才（签约）", notes = "编辑签约人才（签约）")
	@RequestMapping(value = "/editMember", method = {RequestMethod.PUT,RequestMethod.POST})
	public Result<String> editMember(@RequestBody CaishuiMember caishuiMember) {
		if(oConvertUtils.isEmpty(caishuiMember.getId()) || oConvertUtils.isEmpty(caishuiMember.getSignImg())){
			return Result.error("参数错误！");
		}
		//签约人才
		CaishuiMember member = imCaishuiMemberService.getById(caishuiMember.getId());
		if(oConvertUtils.isEmpty(member)) {
			return Result.error("签约人才不存在！");
		}

		//公司信息
		CaishuiServiceCompany company = imCaishuiServiceCompanyService.getById(member.getCompanyId());
		if(oConvertUtils.isEmpty(company)){
			return Result.error("服务公司不存在！");
		}
		//商户信息
		CaishuiBusiness business = imCaishuiBusinessService.getById(member.getBusinessId());
		if(oConvertUtils.isEmpty(business)){
			return Result.error("签约商户不存在！");
		}
		//签约服务类型
		String signingService = imCaishuiSigningServiceTypeService.queryServiceTypeByIds(member.getSigningServiceId());
		if(oConvertUtils.isEmpty(signingService)){
			return Result.error("服务类型不存在！");
		}

		//处理签约文件
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("companyName", company.getName());
		data.put("companyCode", company.getBusinessLicenseNo());
		data.put("name", member.getName());
		data.put("idCard", member.getIdCard());
		data.put("signService", signingService);
		data.put("businessName", business.getName());
		data.put("signDate", DateUtils.sdf.format(new Date()));
		//http字符串转https字符串，如果这里不需要转，则需要修改小程序端
		String image = caishuiMember.getSignImg();
		if (caishuiMember.getSignImg().indexOf("http://") != -1) {
			image = "https://" + caishuiMember.getSignImg().split("http://")[1];
		}
		data.put("signName_af_image", image);//图片全路径，可访问
		String bizPath = "uploadImg/member/sign/" + business.getId();
		String fileName = "自由职业者服务协议_" + member.getName() + "_" + member.getIdCard() + "_" + RandomUtil.randomNumbers(5) + ".pdf";
		String path = upLoadPath + "/" + bizPath + "/" + fileName;
		boolean bool = PDFutils.pdfDataPaddingSign(data,path,fileName);
		if(!bool){
			log.error("生成签约PDF文件失败：" + member.getId());
			return Result.error("签约失败！");
		}

		//文件上传
		String savePath = fileUpload(path, bizPath + "/" + fileName);
		if(oConvertUtils.isEmpty(savePath)){
			log.error("上传签约文件失败：" + member.getId());
			return Result.error("签约失败！");
		}

		member.setSigningFile(savePath);//签约文件
		member.setSigningStatus(2);
		imCaishuiMemberService.updateById(member);
		return Result.OK("签约成功!",member.getSigningFile());
	}

	/**
	 * 文件上传到指定服务器
	 * @param filePath 文件路径
	 * @param bizPath 上传路径
	 * @return
	 */
	public String fileUpload(String filePath, String bizPath){
		String savePath = "";//数据库保存路径
		try {
			//上传
			InputStream inputStream = new BufferedInputStream(new FileInputStream(filePath));
			savePath = MinioUtil.upload(inputStream,bizPath);
			//上传成功之后删除本地文件
			if(oConvertUtils.isNotEmpty(savePath)){
				File file = new File(filePath);
				if(file.exists()) file.delete();
			}
		}catch (Exception e){
			log.error("文件上传失败：" + e.getMessage());
		}
		return savePath;
	}

	/**  图片上传格式  **/
	public static final String suffixs[] = {".jpg",".png",".jpeg",".bmp"};

	/**
	 * 上传身份证
	 * @param request
	 * @return
	 * @throws Exception
	 */
	@ApiOperation(value = "上传身份证", notes = "上传身份证")
	@PostMapping(value = "/uploadIdCard")
	public Result<?> uploadIdCard(HttpServletRequest request,@RequestParam(name="biz",required=false) String biz) throws Exception {
		String savePath = "";//数据库保存路径
		String bizPath = "";
		if(oConvertUtils.isEmpty(biz)){
			bizPath = "member/sfz/";
		}else {
			bizPath = biz;
		}

		//商户信息
		String businessId = bizPath.split("/")[2];
		if (oConvertUtils.isEmpty(businessId)) return Result.error("参数错误！");
		CaishuiBusiness business = imCaishuiBusinessService.getById(businessId);
		if(oConvertUtils.isEmpty(business)){
			return Result.error("签约商户不存在！");
		}

		//图片文件夹标记
		bizPath = "uploadImg/" + bizPath;

		//获取请求过来的文件对象
		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		MultipartFile file = multipartRequest.getFile("file");// 获取上传文件对象

		//获取原文件名
		String orgName = file.getOriginalFilename();
		if(oConvertUtils.isEmpty(orgName)){
			return Result.error("文件对象不能为空！");
		}
		//运算转换单位（保留2位小数）--- 转换单位为MB
		double fileSizeMB = new BigDecimal(file.getSize()/1024/1024).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
		if (fileSizeMB > 10) {
			return Result.error("文件不能超过10M！");
		}
		// 文件名后缀处理---start---  .jsp
		String suffix_z = orgName.substring(orgName.lastIndexOf("."), orgName.length());
		if(!useLoop(suffixs, suffix_z)){
			return Result.error("文件格式错误！");
		}

		//根据配置的文件上传类型选择文件上传
		savePath = MinioUtil.upload(file,bizPath,null);//minio文件上传
		if(oConvertUtils.isEmpty(savePath)){
			return Result.error("上传失败！");
		}
		return Result.ok("上传成功！",savePath);
	}

	//使用简单的循环语句判断数组中是否包含某个字符
	public static boolean useLoop(String[] arr, String targetValue) {
		for (String s : arr) {
			if (s.equals(targetValue)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 获取临时令牌
	 * 模拟登陆接口，获取模拟 Token
	 * @return
	 */
	public static String getTemporaryToken() {
		RedisUtil redisUtil = SpringContextUtils.getBean(RedisUtil.class);
		//模拟登录生成临时Token（必须数据库正常用户）
		String username = "loginAccount";
		//参数说明：第一个参数是用户名、第二个参数是密码的加密串
		String token = JwtUtil.sign(username, "??");
		// 设置Token缓存有效时间为 5 分钟
		redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + username, token);
		redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + username, 5 * 60 * 1000);
		return token;
	}

}
